home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 October: Windmill on DISC / ADC Developer CD (1993-10) (''Windmill On DISC'')_iso / Dev.CD Oct 93.iso / Utilities / Installer v3.4.3 / Examples - Installer 3.4 / Action Atom Samples / InstallFileOnBootVolAA / InstallFileOnBootVol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  14.4 KB  |  513 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  *
  3.  *    Apple Macintosh Developer Technical Support
  4.  *
  5.  *  Installer 3.4 sample: Action Atoms
  6.  *
  7.  *    File:        InstallFileOnBootVol.c -    c Source
  8.  *
  9.  *    by:            Rich Kubota
  10.  *
  11.  *    Copyright © 1990-1992 Apple Computer, Inc.
  12.  *    All rights reserved.
  13.  *
  14.  *    Purpose: Sample to demonstrate the use of an installation action atom to
  15.  *        install a file on the boot volume, regardless of the destination volume
  16.  *        selected by the user.  This allows for the installation of System Files.
  17.  *        To use the atom, define the 'infa' resource as you would normally.  
  18.  *        Instead of including the 'infa' resource in a package resource, pass the
  19.  *        reference as the selector to the action atom.  The atom will use the
  20.  *        source file 'infs' spec to find the file to copy, and use the target 
  21.  *        'infs' spec to define where to install the file.  
  22.  *
  23.  *        Limitations: 
  24.  *        1. This action atom is not compatible with network installations
  25.  *        as the code resource expects the file to exist in the fully qualified
  26.  *        path name defined in the source 'infs' resource.  
  27.  *        2. The source floppy disk name and the source 'infs' resource volume 
  28.  *        name must match.  Unless modified this action atom will not work in a 
  29.  *        network installation.  To overcome this limitation, the search criteria
  30.  *        for source files specified in the Installer Guide, must be incorporated.
  31.  *        3. The code resource overwrites an existing file, and does not restore
  32.  *        the file if the installation is cancelled or aborted.  There is no check
  33.  *        as to whether the existing file is later than the one to be installed.
  34.  *        4. There is no check to make sure that there is sufficient space before
  35.  *        trying to replace/create the file.
  36.  *        5. There is no warning given that a problem occured, nor what the problem
  37.  *        was.
  38.  *        6. The Finder info of the source will be copied along with the file to the
  39.  *        target file.
  40.  *        7. If the special folder designations are not used, the Installer returns
  41.  *        an error.
  42.  *        8. This action will not work with system 6.0.x and will return an error.
  43.  *
  44.  *        All of the above limitations can be overcome, and are left as exercises 
  45.  *        to the scriptwriter.
  46.  *        
  47.  *
  48.  *    
  49.      Algorithm:
  50.         1. Entry point - main
  51.         2. Get the 'infa' resource based on the ID passed in as the action 
  52.             atom selector.  Return false if not found.
  53.         3. Parse the 'infs' resource and get the source and target 'infs' resource
  54.             IDs.
  55.         4. Get the source 'infs' resource, make local copy, and release the handle.
  56.         5. Do the same for the target 'infs' resource. Return false if not found
  57.         6. Call the CopyFile routine.
  58.         7. Ensure that the first 12 characters of the target pathname are lower
  59.             case so that we can do comparisons on them.
  60.         8. Call SysEnvirons to get the vRefNum (-1) and DirID of the System Folder
  61.             on the boot volume. Return false if not found.
  62.         9. Take the target pathname and convert the special folder designation to
  63.             a usable path name relative to the System Folder.  Return false if the
  64.             folder type is not recognized.
  65.        10. A check is made to see if the target file already exists.  Nothing is 
  66.                done if the file is found.
  67.        11. Allocate a 20K buffer to use in copying.
  68.        12. Call the copy fork routine to copy the data fork.
  69.        12a. The source file is opened.
  70.        12b. The destination file is opened.
  71.        12c. If the destination file does not exist, create it, then open the file.
  72.        12d. Copy the file using FSRead and FSWrite, then close each file.
  73.                return false if error occurs.
  74.        13. Call the CopyFork routine to copy the resource fork using the same 
  75.                algorith in step 12. return false if error occurs.
  76.        14. Copy the Finder info from the source to the target. return false if error
  77.                occurs.
  78.        15. Return true if the previous steps worked without error.
  79.  
  80.  *----------------------------------------------------------------------------*/
  81.  
  82. #if 0
  83.  
  84. The following are build instructions for this code under MPW.
  85.  
  86. C -r -b  InstallFileOnBootVol.c
  87. Link -ra =resPurgeable -t rsrc -c RSED -rt infn=10000 ∂
  88.     -m INSTALLFILEONBOOTVOL -sg InstallFileOnBootVol ∂
  89.     InstallFileOnBootVol.c.o ∂
  90.     "{Libraries}"Interface.o ∂
  91.     "{CLibraries}"StdCLib.o ∂
  92.     -o InstallFileOnBootVol.rsrc
  93.  
  94. #endif
  95.  
  96. #ifndef THINK_C
  97. #include <Types.h>
  98. #include <Resources.h>
  99. #include <Files.h>
  100. #include <Errors.h>
  101. #include <Memory.h>
  102. #endif
  103.  
  104. #include <String.h>
  105. #include "ActionAtomIntf.h"
  106.  
  107. /* define record structure of 'infs' resource so that we can access the target file path */
  108.  
  109. struct infaRec {
  110.     short            version;
  111.     short            flags;
  112.     short            tgtRsrcID;
  113.     short            srcRsrcID;
  114.     unsigned long    fSize;
  115.     Str255            description;
  116. };
  117.  
  118. typedef struct infaRec infaRec;
  119. typedef infaRec **infaHdl;
  120.  
  121. struct infsRec {
  122.     long    fileType;
  123.     long    creator;
  124.     long    creationDate;
  125.     short    fileSpecFlags;
  126.     Str255    pathName;
  127.     short    vRefNum;
  128.     long    dirID;
  129.     short    fRefNum;
  130.     Ptr        buffPtr;
  131.     long    buffSize;
  132.     Boolean sys7Flag;
  133. };
  134.  
  135. typedef struct infsRec infsRec;
  136. typedef infsRec *infsPtr, **infsHdl;
  137.  
  138. #define BTstQ(arg, bitnbr)    (arg & (1 << bitnbr))
  139. #define NIL                 0L
  140. #define FALSE                0
  141. #define ERROR                -1
  142. #define kSpecialLength        7
  143. #define kData                1
  144. #define kResource            2
  145. #define kCopyBufferSize        20480L
  146.  
  147. /* protoypes */
  148. void    MakeSpecialStrLower(char *str);
  149. OSErr    FindSysFolder(infsPtr tgtInfsPtr);
  150. OSErr    ConvertSpecialFolderName(infsPtr tgtInfsPtr);
  151. Boolean    FileExists(infsPtr tgtInfsPtr);
  152. OSErr    DoOpenDF(infsPtr fInfsPtr, char permission);
  153. OSErr    DoOpenRF(infsPtr fInfsPtr, char permission);
  154. OSErr    OpenFiles(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork);
  155. OSErr    SetDestinationFileSize(infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
  156. OSErr    CopyFork(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork);
  157. OSErr    TransferCatInfo(infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
  158. OSErr    CopyFiles (infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
  159.  
  160. #ifndef THINK_C
  161. pascal long    INSTALLFILEONBOOTVOL (AAPBRecPtr myAAPBPtr)
  162. #else
  163. pascal long main ((AAPBRecPtr myAAPBPtr)
  164. #endif
  165. {
  166.     OSErr    err;
  167.     Handle    tempH;
  168.     infaHdl    myInfaHdl;
  169.     infsRec srcInfs, tgtInfs;
  170.  
  171.     /* determine whether the 'after' stage is current, else the action atom will also
  172.        be called at the cancel stage should another action atom report a problem.
  173.     /* get the 'infa' resource handle */
  174.     
  175.     if (myAAPBPtr->whichStage == after) {
  176.         myInfaHdl = (infaHdl)GetResource('infa', myAAPBPtr->aaRefCon);
  177.     
  178.         /* was it found ? */
  179.         if (myInfaHdl == NIL)
  180.             return FALSE;
  181.     
  182.         /* get the source 'infs' resources */
  183.         tempH = GetResource('infs', (*myInfaHdl)->srcRsrcID);
  184.         if (tempH == NIL)
  185.             return FALSE;
  186.         BlockMove(*tempH, &srcInfs, sizeof(infsRec));
  187.         ReleaseResource(tempH);
  188.         srcInfs.vRefNum = 0;
  189.     
  190.         /* get the target 'infs' resources */
  191.         tempH = GetResource('infs', (*myInfaHdl)->tgtRsrcID);
  192.         if (tempH == NIL)
  193.             return FALSE;
  194.         BlockMove(*tempH, &tgtInfs, sizeof(infsRec));
  195.         ReleaseResource(tempH);
  196.         
  197.         err = CopyFiles(&srcInfs, &tgtInfs);
  198.     
  199.          
  200.         return (err);
  201.     }
  202.     else
  203.         return noErr;
  204. }
  205.  
  206. void    MakeSpecialStrLower(char *str)
  207. {
  208.     short    len, i;
  209.  
  210.     len = 12;        /* make lower case, first 12 characters "Special-Fold" -> "special-fold" */
  211.     
  212.     for(i = 1; i <= len; i++)
  213.         if ((str[i] >= 'A') && (str[i] <= 'Z'))
  214.             str[i] += 'a' - 'A';
  215. }
  216.  
  217.  
  218. OSErr    FindSysFolder(infsPtr tgtInfsPtr)
  219. {
  220.     SysEnvRec        envRec;
  221.     WDPBRec            myWDPB;
  222.     unsigned char    volName[34];
  223.     OSErr            err;
  224.     
  225.     
  226.     tgtInfsPtr->vRefNum = 0;
  227.     tgtInfsPtr->dirID = 0;
  228.     if (!(err = SysEnvirons (curSysEnvVers, &envRec))) 
  229.     {
  230.         /* set flag to indicate whether system 7 or not */
  231.         tgtInfsPtr->sys7Flag = (envRec.systemVersion >= 0x0700);
  232.         
  233.         myWDPB.ioVRefNum = envRec.sysVRefNum;
  234.         volName[0] = '\000';                    /* Zero volume name */
  235.         myWDPB.ioNamePtr = (StringPtr)volName;
  236.         myWDPB.ioWDIndex = 0;
  237.         myWDPB.ioWDProcID = 0;
  238.         if (!(err = PBGetWDInfo (&myWDPB, 0))) 
  239.         {
  240.             tgtInfsPtr->vRefNum = myWDPB.ioWDVRefNum;
  241.             tgtInfsPtr->dirID = myWDPB.ioWDDirID;
  242.         }
  243.     }
  244.     return (err);
  245. }
  246.  
  247.  
  248. OSErr    ConvertSpecialFolderName(infsPtr tgtInfsPtr)
  249. {
  250.     ResType    folderType;
  251.     char    *tempStr;
  252.     char    systemName[] = "\pspecial";
  253.     short    saveLen, curLen;
  254.     
  255.     /* save length of original path name string */
  256.     saveLen = tgtInfsPtr->pathName[0];
  257.     
  258.     /* make a working copy of the target path name */
  259.     tempStr = NewPtr(sizeof(Str255));
  260.     if (tempStr == nil)
  261.         return ERROR;
  262.     
  263.     BlockMove(tgtInfsPtr->pathName, tempStr, sizeof(Str255));
  264.     
  265.     /* first let's make sure that the path name specifies the System Folder
  266.      * as the destination.  Have already passed the name through a filter to
  267.      * make each char all lower case 
  268.      */
  269.     if (memcmp(&systemName[1], &tempStr[1], kSpecialLength) != 0)
  270.         return ERROR;
  271.     
  272.     if (tgtInfsPtr->sys7Flag)
  273.     {
  274.     
  275.         /* set the tempstr ptr to point to the beginning of the special
  276.          * folder ID
  277.          */
  278.         tempStr += (kSpecialLength + 2L); /* need to point past the hyphen character
  279.                                            * and need to take into account the length
  280.                                            * byte at the begin of str 
  281.                                            */
  282.         memcpy((char*)&folderType, tempStr, 4);
  283.         switch( folderType)
  284.         {
  285.             case 'macs':
  286.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p");
  287.                 break;
  288.             case 'prnt':
  289.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:PrintMonitor Documents:");
  290.                 break;
  291.             case 'strt':
  292.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Startup Items:");
  293.                 break;
  294.             case 'amnu':
  295.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Apple Menu Items:");
  296.                 break;
  297.             case 'extn':
  298.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Extensions:");
  299.                 break;
  300.             case 'pref':
  301.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Preferences:");
  302.                 break;
  303.             case 'ctrl':
  304.                 strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Control Panels:");
  305.                 break;
  306.             default:
  307.                 DisposPtr(tempStr);
  308.                 return ERROR;
  309.         }
  310.     }
  311.     else
  312.     {
  313.         /* clear out the pathname in 'pathName' field */
  314.         tgtInfsPtr->pathName[0] = 0;
  315.         /* move the tempStr ptr to point to the beginning of the special folder 
  316.          *  ID.  In System 6, all files get copied into the System Folder
  317.          */
  318.         tempStr += (kSpecialLength + 2L);
  319.     }
  320.  
  321.     /* now position tempStr to point to the character following the ":" and the folder
  322.      * type and concatenate the rest of the string to tgtInfsPtr->pathName
  323.      */
  324.     tempStr += 5L;
  325.     curLen = tgtInfsPtr->pathName[0];
  326.     
  327.     /* when copying, take into account the hyphen and folder manager characters & hyphen (6) */
  328.     memcpy(&(tgtInfsPtr->pathName[curLen+1]), tempStr, saveLen - kSpecialLength - 6);
  329.     tgtInfsPtr->pathName[0] += (saveLen - kSpecialLength - 6);
  330.     DisposPtr(tempStr);
  331.     return noErr;
  332. }
  333.  
  334. Boolean    FileExists(infsPtr tgtInfsPtr)
  335. {
  336.     HParamBlockRec    pb;
  337.     
  338.     pb.fileParam.ioCompletion = nil;
  339.     pb.fileParam.ioNamePtr = (StringPtr)&tgtInfsPtr->pathName;
  340.     pb.fileParam.ioVRefNum = tgtInfsPtr->vRefNum;
  341.     pb.fileParam.ioFDirIndex = 0;
  342.     pb.fileParam.ioDirID = tgtInfsPtr->dirID;
  343.     return (PBHGetFInfoSync(&pb) == noErr);
  344. }
  345.  
  346. OSErr    DoOpenDF(infsPtr fInfsPtr, char permission)
  347. {
  348.     HParamBlockRec    pbh;
  349.     OSErr        err;
  350.  
  351.     pbh.fileParam.ioCompletion = nil;
  352.     pbh.fileParam.ioNamePtr = (StringPtr)&fInfsPtr->pathName;
  353.     pbh.fileParam.ioVRefNum = fInfsPtr->vRefNum;
  354.     pbh.ioParam.ioPermssn = permission;
  355.     pbh.ioParam.ioMisc = nil;
  356.     pbh.fileParam.ioDirID = fInfsPtr->dirID;
  357.     err = PBHOpen(&pbh, false);
  358.     fInfsPtr->fRefNum = pbh.ioParam.ioRefNum;
  359.     return err;
  360. }
  361.  
  362.  
  363. OSErr    DoOpenRF(infsPtr fInfsPtr, char permission)
  364. {
  365.     HParamBlockRec    pbh;
  366.     OSErr        err;
  367.  
  368.     pbh.fileParam.ioCompletion = nil;
  369.     pbh.fileParam.ioNamePtr = (StringPtr)&fInfsPtr->pathName;
  370.     pbh.fileParam.ioVRefNum = fInfsPtr->vRefNum;
  371.     pbh.ioParam.ioPermssn = permission;
  372.     pbh.ioParam.ioMisc = nil;
  373.     pbh.fileParam.ioDirID = fInfsPtr->dirID;
  374.     err = PBHOpenRF(&pbh, false);
  375.     fInfsPtr->fRefNum = pbh.ioParam.ioRefNum;
  376.     return err;
  377. }
  378.  
  379. OSErr    OpenFiles(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork)
  380. {
  381.     typedef OSErr (*OpenProcPtr) (infsPtr fInfsPtr, char permission);
  382.     
  383.     OpenProcPtr    openProc;
  384.     OSErr        err;
  385.     HParamBlockRec    pbh;
  386.     
  387.     if (whichFork == kData)
  388.     {
  389.         openProc = DoOpenDF;
  390.     }
  391.     else
  392.     {
  393.         openProc = DoOpenRF;
  394.     }
  395.     err = openProc(srcInfsPtr, fsRdPerm);
  396.     if (err != noErr)
  397.         return err;
  398.     
  399.     err = openProc(tgtInfsPtr, fsRdWrPerm);
  400.     if (err == fnfErr)
  401.     {
  402.         pbh.fileParam.ioCompletion = nil;
  403.         pbh.fileParam.ioNamePtr = (StringPtr)&tgtInfsPtr->pathName;
  404.         pbh.fileParam.ioVRefNum = tgtInfsPtr->vRefNum;
  405.         pbh.fileParam.ioDirID = tgtInfsPtr->dirID;
  406.         err = PBHCreate(&pbh, false);
  407.         if (err == noErr)
  408.             err = openProc(tgtInfsPtr, fsRdWrPerm);
  409.     }
  410.     if (err != noErr)
  411.         FSClose(srcInfsPtr->fRefNum);
  412.     return err;
  413. }
  414.  
  415.  
  416. OSErr    SetDestinationFileSize(infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
  417. {
  418.     OSErr    err;
  419.     long    forkSize;
  420.     
  421.     err = GetEOF(srcInfsPtr->fRefNum, &forkSize);
  422.     if (err == noErr)
  423.         err = SetEOF(tgtInfsPtr->fRefNum, forkSize);
  424.     return err;
  425. }
  426.  
  427.  
  428. OSErr    CopyFork(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork)
  429. {
  430.     OSErr    err;
  431.     Boolean    done = FALSE;
  432.     
  433.     err = OpenFiles(srcInfsPtr, tgtInfsPtr, whichFork);
  434.     if (err != noErr)
  435.         return ERROR;
  436.     err = SetDestinationFileSize(srcInfsPtr, tgtInfsPtr);
  437.     if (err != noErr)
  438.         return ERROR;
  439.     
  440.     do 
  441.     {
  442.         srcInfsPtr->buffSize = kCopyBufferSize;
  443.         err = FSRead(srcInfsPtr->fRefNum, &srcInfsPtr->buffSize, srcInfsPtr->buffPtr);
  444.         if (err == eofErr)
  445.         {
  446.             err = noErr;
  447.             done = true;
  448.         }
  449.         if (err == noErr)
  450.             err = FSWrite(tgtInfsPtr->fRefNum, &srcInfsPtr->buffSize, srcInfsPtr->buffPtr);
  451.     } while (!done && (err == noErr));
  452.  
  453.     FSClose(srcInfsPtr->fRefNum);
  454.     FSClose(tgtInfsPtr->fRefNum);
  455.     
  456.     return err;
  457. }
  458.  
  459.  
  460. OSErr    TransferCatInfo(infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
  461. {
  462.     CInfoPBRec    pb;
  463.     OSErr        err;
  464.     
  465.     pb.hFileInfo.ioVRefNum = srcInfsPtr->vRefNum;
  466.     pb.hFileInfo.ioNamePtr = (StringPtr)srcInfsPtr->pathName;
  467.     pb.hFileInfo.ioFDirIndex = 0;
  468.     pb.hFileInfo.ioDirID = srcInfsPtr->dirID;
  469.     err = PBGetCatInfoSync(&pb);
  470.     
  471.     if (err == noErr)
  472.     {
  473.         pb.hFileInfo.ioVRefNum = tgtInfsPtr->vRefNum;
  474.         pb.hFileInfo.ioNamePtr = (StringPtr)tgtInfsPtr->pathName;
  475.         pb.hFileInfo.ioFDirIndex = 0;
  476.         pb.hFileInfo.ioDirID = tgtInfsPtr->dirID;
  477.         err = PBSetCatInfoSync(&pb);
  478.     }
  479.     return err;
  480. }
  481.  
  482.  
  483. OSErr    CopyFiles (infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
  484. {
  485.     OSErr    err;
  486.     
  487.     MakeSpecialStrLower((char *)tgtInfsPtr->pathName);
  488.     err = FindSysFolder(tgtInfsPtr);
  489.     if (err != noErr)
  490.         return ERROR;
  491.  
  492.     if (ConvertSpecialFolderName(tgtInfsPtr) != noErr)
  493.         return ERROR;
  494.     
  495.     if (FileExists(tgtInfsPtr))
  496.     {
  497.         /* we could check here that the target file did not already exist and
  498.          * do something appropriate like rename the old file.
  499.          */
  500.     }
  501.     srcInfsPtr->buffPtr = NewPtr(kCopyBufferSize);
  502.     if (srcInfsPtr->buffPtr == NIL)
  503.         return MemError();
  504.     
  505.     err = CopyFork(srcInfsPtr, tgtInfsPtr, kData);
  506.     if (err == noErr)
  507.         err = CopyFork(srcInfsPtr, tgtInfsPtr, kResource);
  508.     if (err == noErr)
  509.         err = TransferCatInfo(srcInfsPtr, tgtInfsPtr);
  510.     
  511.     DisposPtr(srcInfsPtr->buffPtr);
  512.     return err;
  513. }